package controll
{
	import com.adobe.utils.DateUtil;
	
	import events.IProjectMouseEventAction;
	import events.ProjectEventViewEvent;
	import events.ProjectorBoardEvent;
	
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import gzgi.utils.TimeUtil;
	
	import module.GlobalTextLabel;
	import module.ProjectEventModule;
	
	import mx.events.FlexEvent;
	import mx.events.ResizeEvent;
	
	import views.IProjectEventView;
	import views.ProjectBoard;
	import views.ProjectEventView;
	import views.RowProjectBoard;

	public class RowProjectEventManager extends ProjectEventManagerBase implements IProjectMouseEventAction
	{
		private var m_state:int;
		private var m_isPress:Boolean = false;
		private static const STATE_READY:int = 1;
		private static const STATE_DRAG:int = 2;
		private static const STATE_INPUT:int = 3;
		private static const STATE_SELECTED:int = 4;
		private static const STATE_EVENT_DRAG:int = 5;
		private static const STATE_EVENT_TOP_EDGE_DRAG:int = 6;
		private static const STATE_EVENT_BOTTOM_EDGE_DRAG:int = 7;
		
		private var m_board:RowProjectBoard;
		private var m_downPoint:Point;
		private var m_projectEvent:ProjectEventModule;
		public function RowProjectEventManager($projectBoard:RowProjectBoard)
		{
			m_board = $projectBoard;
			m_state = STATE_READY;
			m_projectEvent = new ProjectEventModule();
		}
		public function initEvents():void
		{
			m_board.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown, false, 0, true);
			m_board.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove, false, 0, true);
			m_board.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp, false, 0, true);
			m_board.addEventListener(MouseEvent.DOUBLE_CLICK, handleMouseDoubleClick, false, 0, true);
			
			m_board.addEventListener(ProjectEventViewEvent.TOP_EDGE_OVER, handleEdgeOver, false, 0, true);
			m_board.addEventListener(ProjectEventViewEvent.BOTTOM_EDGE_OVER, handleEdgeOver, false, 0, true);
			m_board.addEventListener(ProjectEventViewEvent.TOP_EDGE_SELECT, handleEdgeSelect, false, 0, true);
			m_board.addEventListener(ProjectEventViewEvent.BOTTOM_EDGE_SELECT, handleEdgeSelect, false, 0, true);
			m_board.addEventListener(ProjectorBoardEvent.DATE_CHANGED, handleDateChanged, false, 0, true);
			
		}
		public function handleDateChanged($event:ProjectorBoardEvent):void
		{
			if (m_board.type == RowProjectBoard.TYPE_WEEK)
			{
				m_board.loadData(TimeUtil.getFirstDateOfWeek(m_board.date), 7); 
			}
			else if (m_board.type == RowProjectBoard.TYPE_SINGLEDATE)
			{
				
				m_board.loadData(m_board.date, 1);
				
			}
			
		}
		public function handleMouseDown($event:MouseEvent):void
		{
			m_isPress = true;
			var point:Point = m_board.eventMousePoint;
			
			if (m_board.gridRect.containsPoint(point))
			{
				m_downPoint = m_board.pointAtGrid(point);
			}
			if (m_state == STATE_READY)
			{
				var selectedView:ProjectEventView = getViewWithMousePosition();
			
				if (selectedView != null)
				{
					m_state = STATE_SELECTED;
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SELECT);
					event.projectEventView = selectedView;
					this.dispatchEvent(event);
				}
			}
			else if (m_state == STATE_SELECTED)
			{
				var selectedView:ProjectEventView = getViewWithMousePosition();
				if (selectedView != null)
				{
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SELECT);
					event.projectEventView = selectedView;
					this.dispatchEvent(event);
				}
				else
				{
		
					m_state = STATE_READY;
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SELECT);
					this.dispatchEvent(event);
					handleMouseDown($event);
				}
			}
			else if (m_state == STATE_EVENT_TOP_EDGE_DRAG || m_state == STATE_EVENT_BOTTOM_EDGE_DRAG)
			{
				var selectedView:ProjectEventView = getViewWithMousePosition();
				if (selectedView != null)
				{
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SELECT);
					event.projectEventView = selectedView;
					this.dispatchEvent(event);
				}
			}
			else if (m_state == STATE_INPUT)
			{
				var view:IProjectEventView = m_board.selectedEvents[0];
				var selectedView:ProjectEventView = getViewWithMousePosition();
				if (selectedView == null || view != selectedView)
				{

					ProjectEventView(view).enableShotEditting = false;
					
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.UPDATE_COMPLETE);
					event.projectEvent = view.source;
					event.projectEventView = view;
					this.dispatchEvent(event);

					if (selectedView == null)
					{
						m_state = STATE_READY;
						var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SELECT);
						this.dispatchEvent(event);
						handleMouseDown($event);
						
					}
					else
					{
						m_state = STATE_SELECTED;
						var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SELECT);
						event.projectEventView = selectedView;
						this.dispatchEvent(event);
					}
				}
			}
		}
		public function handleMouseUp($event:MouseEvent):void
		{
			m_isPress = false;
			
			switch(m_state)
			{
				case STATE_DRAG:
					m_state = STATE_INPUT;
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.CREATE);
					var eventModule:ProjectEventModule = getProjectEventModuleWithMouseEvent(m_board.pointAtGrid(m_board.eventMousePoint), this.m_downPoint);
					var projectEventModule:ProjectEventModule = ProjectEventModule.createInstance();
					projectEventModule._startTime(eventModule.startTime)._endTime(eventModule.endTime)._title(GlobalTextLabel.DEFAULT_TITLE);
					event.projectEvent = projectEventModule;
					this.dispatchEvent(event);
					break;
				case STATE_EVENT_DRAG:
					m_state = STATE_SELECTED;
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.UPDATE_COMPLETE);
					var eventModule:ProjectEventModule = getNewProjectEventModuleWithMouseEvent();
					event.projectEvent = m_board.selectedEvents[0].source._startTime(eventModule.startTime)._endTime(eventModule.endTime) as ProjectEventModule;
					event.projectEventView = m_board.selectedEvents[0];
					this.dispatchEvent(event);
					break;
				case STATE_EVENT_TOP_EDGE_DRAG:
				case STATE_EVENT_BOTTOM_EDGE_DRAG:
					
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.UPDATE_COMPLETE);
					eventModule = getNewProjectEventModuleWithEdgeDragEvent(m_board.pointAtGrid(m_board.eventMousePoint), m_state);
					m_state = STATE_SELECTED;
					event.projectEvent = m_board.selectedEvents[0].source._startTime(eventModule.startTime)._endTime(eventModule.endTime) as ProjectEventModule;
					event.projectEventView = m_board.selectedEvents[0];
					this.dispatchEvent(event);
					
			}
			m_downPoint = null;
			
		}
		public function handleMouseMove($event:MouseEvent):void
		{
			var eventModule:ProjectEventModule;
			// switch state detected
			if (m_state == STATE_READY && m_isPress && m_downPoint)
			{
				m_state = STATE_DRAG;
			}
			else if (m_state == STATE_SELECTED && m_isPress)
			{
				m_state = STATE_EVENT_DRAG
			}
			
			//state actions
			var point:Point = m_board.eventMousePoint;
			if (m_state == STATE_DRAG)
			{
				//drag the mouse and create a event;
				var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.DRAG);
				eventModule = getProjectEventModuleWithMouseEvent(m_downPoint, m_board.pointAtGrid(point));
				eventModule._title(GlobalTextLabel.DEFAULT_TITLE);
				event.projectEvent = eventModule;
				this.dispatchEvent(event);
			}
			else if (m_state == STATE_EVENT_DRAG)
			{
				//select a event and drag it to change time
				
				eventModule = getNewProjectEventModuleWithMouseEvent();

				var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.UPDATING);
				event.projectEvent = eventModule;
				event.projectEventView = m_board.selectedEvents[0];
				this.dispatchEvent(event);
			}
			else if (m_state == STATE_EVENT_TOP_EDGE_DRAG || m_state == STATE_EVENT_BOTTOM_EDGE_DRAG)
			{
				eventModule = getNewProjectEventModuleWithEdgeDragEvent(m_board.pointAtGrid(m_board.eventMousePoint), m_state);
				var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.UPDATING);
				event.projectEvent = eventModule;
				event.projectEventView = m_board.selectedEvents[0];
				this.dispatchEvent(event);
				
			}
			
		}
		private function handleEdgeOver($event:ProjectEventViewEvent):void
		{
//			$event.stopPropagation();
			this.dispatchEvent($event);
		}
		private function handleEdgeSelect($event:ProjectEventViewEvent):void
		{

			if ($event.type == ProjectEventViewEvent.TOP_EDGE_SELECT)
			{
				this.m_state = STATE_EVENT_TOP_EDGE_DRAG;
			}
			else if ($event.type == ProjectEventViewEvent.BOTTOM_EDGE_SELECT)
			{
				this.m_state = STATE_EVENT_BOTTOM_EDGE_DRAG;
			}
			
//			$event.stopPropagation();
			this.dispatchEvent($event);
		}

		public function handleMouseDoubleClick($event:MouseEvent):void
		{
			if (m_state == RowProjectEventManager.STATE_SELECTED || m_state == RowProjectEventManager.STATE_READY)
			{
				var selectedView:ProjectEventView = getViewWithMousePosition();
				if (selectedView != null)
				{
					var event:ProjectEventViewEvent = new ProjectEventViewEvent(ProjectEventViewEvent.SHOW_DETAIL_WIN, true, true);
					event.projectEvent = selectedView.source;
					event.projectEventView = selectedView;
					m_board.dispatchEvent(event);
				}
			}
		}
		private function getProjectEventModuleWithMouseEvent(p1:Point, p2:Point):ProjectEventModule
		{
			var date1:Date = getDateTimeWithPoint(p1);
			var date2:Date = getDateTimeWithPoint(p2);
			
			var startDate:Date = date1 < date2 ? date1 : date2;
			var endDate:Date = date1 < date2 ? date2 : date1;
			var eventModule:ProjectEventModule = new ProjectEventModule()._startTime(startDate)._endTime(endDate) as ProjectEventModule;
			return eventModule;
		}
		private function getNewProjectEventModuleWithMouseEvent():ProjectEventModule
		{
			var eventModule:ProjectEventModule;
			var point:Point = m_board.eventMousePoint.subtract(this.m_downPoint);
			var pointAtGrid:Point = m_board.pointAtGrid(m_board.eventMousePoint);
			
			var minutes:Number = RowProjectBoard.pixelsToMinutes(point.y, m_board.gridRect.height);
			eventModule = new ProjectEventModule();
			var sourceEventModule:ProjectEventModule = m_board.selectedEvents[0].source;
			var sourceDateDiff:Number = Math.floor(this.m_downPoint.x / (m_board.gridRect.width / m_board.columns));
			var newDateDiff:Number = Math.floor(pointAtGrid.x / (m_board.gridRect.width / m_board.columns));
			var dateDiff:Number = newDateDiff - sourceDateDiff;
			var startDate:Date = sourceEventModule.startTime;
			var endDate:Date = sourceEventModule.endTime;
			startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + dateDiff, startDate.getHours(), startDate.getMinutes() + minutes, startDate.getSeconds(), startDate.getMilliseconds());
			endDate = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate() + dateDiff, endDate.getHours(), endDate.getMinutes() + minutes, endDate.getSeconds(), endDate.getMilliseconds());
			eventModule._startTime(startDate);
			eventModule._endTime(endDate);

			return eventModule;
		}
		private function getNewProjectEventModuleWithEdgeDragEvent($point:Point, $stateType:int):ProjectEventModule
		{
			var eventModule:ProjectEventModule;
			eventModule = new ProjectEventModule();
			var date1:Date;
			var date2:Date;
			if ($stateType == STATE_EVENT_TOP_EDGE_DRAG)
			{
				date1 = this.getDateTimeWithPoint($point);
				date2 = m_board.selectedEvents[0].source.endTime;
			}
			else if ($stateType == STATE_EVENT_BOTTOM_EDGE_DRAG)
			{
				date2 = this.getDateTimeWithPoint($point);
				date1 = m_board.selectedEvents[0].source.startTime;
			}
			var startDate:Date = date1 < date2 ? date1 : date2;
			var endDate:Date = date2 > date1 ? date2 : date1;
			eventModule._startTime(startDate)._endTime(endDate);
			return eventModule;
		}
		private function getViewWithMousePosition():ProjectEventView
		{
			
			var point:Point = new Point(m_board.mouseX, m_board.mouseY);
			var selectedView:ProjectEventView;
			if (!m_board.gridRect.containsPoint(point))
			{
				return selectedView;
			}
			for (var i:Number = 0; i < m_board.eventPanelLayer.numElements; i++)
			{
				var globalPoint:Point = m_board.localToGlobal(point);
				var view:ProjectEventView = m_board.eventPanelLayer.getElementAt(i) as ProjectEventView;
				if (view.hitTestPoint(globalPoint.x, globalPoint.y, true))
				{
					selectedView = view;
					break;
				}
			}
			return selectedView;
		}
		private function getDateTimeWithPoint($point:Point):Date
		{
			var minutes = RowProjectBoard.pixelsToMinutes($point.y, m_board.gridRect.height);
//			trace (minutes);
			var date:Date;
			var targetDate:Date;
			if (m_board.type == RowProjectBoard.TYPE_SINGLEDATE)
			{
				targetDate = m_board.date;
			}
			else if (m_board.type == RowProjectBoard.TYPE_WEEK)
			{
				var diff:Number = Math.floor($point.x / (m_board.gridRect.width / 7));
				var firstDate:Date = TimeUtil.getFirstDateOfWeek(m_board.date);
				targetDate = TimeUtil.getDateWithDateAddDifferent(firstDate, diff);

			}
			date = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate(), 0, minutes);
			return date;
		}
		public function abfc()
		{
			
		}
//		public function handleMouseUp($
	}
}